evtchn/fifo: only set READY for new heads
authorDavid Vrabel <david.vrabel@citrix.com>
Mon, 25 Nov 2013 10:15:05 +0000 (11:15 +0100)
committerJan Beulich <jbeulich@suse.com>
Mon, 25 Nov 2013 10:15:05 +0000 (11:15 +0100)
Setting a queue's READY bit for every event added to the queue
introduces a race.

If an event is added to the tail of a queue, the guest may consume the
newly added event and leave an empty queue before the READY is set.
The guest may then see a stale HEAD value and if the event at the
stale head became linked onto a different queue, the guest would
consume events from the wrong queue (corrupting it).

As noted in section 4.1.2 of the design document, only set READY if a
new HEAD is set.  This ensures that if the guest sees a READY bit set
the corresponding HEAD is valid.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
xen/common/event_fifo.c

index 9106c55f9ae145f7f2c2ed4288d851b3ee8bcfd1..6048784bc6f8f4a51d804caa04d15dfcb60a3ffb 100644 (file)
@@ -161,8 +161,9 @@ static void evtchn_fifo_set_pending(struct vcpu *v, struct evtchn *evtchn)
 
         spin_unlock_irqrestore(&q->lock, flags);
 
-        if ( !test_and_set_bit(q->priority,
-                               &v->evtchn_fifo->control_block->ready) )
+        if ( !linked
+             && !test_and_set_bit(q->priority,
+                                  &v->evtchn_fifo->control_block->ready) )
             vcpu_mark_events_pending(v);
     }